package com.sky.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.exception.SetmealEnableFailedException;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.CategoryService;
import com.sky.service.DishService;
import com.sky.service.SetmealDishService;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static org.apache.commons.lang3.ObjectUtils.min;

@Service
public class SetmealServiceimpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

    @Autowired
    private SetmealMapper setmealMapper;

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private DishService dishService;

    @Autowired
    private CategoryService categoryService;

    @Override
    public List<DishItemVO> getDishItemById(Long id) {

        // 查询套餐包含的菜品信息
        List<SetmealDish> setmealDishList = setmealDishService.getBySetmealId(id);

        List<DishItemVO> dishItemVOList = new ArrayList<>();

        // 遍历每条套餐菜品数据，生成查询结果
        for (SetmealDish setmealDish : setmealDishList) {
            Long dishId = setmealDish.getDishId();
            Dish dish = dishService.queryById(dishId);

            // 填充查询结果信息
            DishItemVO dishItemVO = new DishItemVO();
            dishItemVO.setName(dish.getName());
            dishItemVO.setCopies(setmealDish.getCopies());
            dishItemVO.setImage(dish.getImage());
            dishItemVO.setDescription(dish.getDescription());

            // 插入返回数据列表
            dishItemVOList.add(dishItemVO);
        }

        return dishItemVOList;
    }


    @Override
    public Long countByCategoryId(Long id) {

        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<Setmeal>()
                .eq(Setmeal::getCategoryId, id);

        return setmealMapper.selectCount(lambdaQueryWrapper);
    }

    @Override
    public List<Setmeal> listByCategoryId(Long categoryId) {
        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<Setmeal>()
                .eq(Setmeal::getCategoryId, categoryId)
                .eq(Setmeal::getStatus, StatusConstant.ENABLE);
        return setmealMapper.selectList(lambdaQueryWrapper);
    }


    /**
     * 新增套餐
     *
     * @param setmealDTO
     * @return
     */
    @Override
    @Transactional
    public Setmeal create(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);

        setmeal.setCreateTime(LocalDateTime.now());
        setmeal.setCreateUser(BaseContext.getCurrentId());

        setmeal.setUpdateTime(LocalDateTime.now());
        setmeal.setUpdateUser(BaseContext.getCurrentId());

        setmealMapper.insert(setmeal);

        setmeal = setmealMapper.selectOne(
                new LambdaQueryWrapper<Setmeal>()
                        .eq(Setmeal::getName, setmeal.getName())
        );

        Long setMealId = setmeal.getId();

        List<SetmealDish> setmealDishList = setmealDTO.getSetmealDishes();
        setmealDishList.forEach(
                setmealDish -> {
                    setmealDish.setSetmealId(setMealId);
                }
        );

        setmealDishService.createBatch(setmealDishList);


        return null;
    }

    @Override
    @Transactional
    public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {

        int pageNum = setmealPageQueryDTO.getPage();
        int pageSize = setmealPageQueryDTO.getPageSize();

        String name = setmealPageQueryDTO.getName();
        Integer categoryId = setmealPageQueryDTO.getCategoryId();
        Integer status = setmealPageQueryDTO.getStatus();

        // 构造分页条件
        Page<Setmeal> page = Page.of(pageNum, pageSize);

        lambdaQuery()
                .like(name != null, Setmeal::getName, name)
                .eq(categoryId != null, Setmeal::getCategoryId, categoryId)
                .eq(status != null, Setmeal::getStatus, status)
                .page(page);

        // 取出查询得到的数据列表
        List<Setmeal> setmealList = page.getRecords();
        // 存放转换后的数据列表
        List<SetmealVO> setmealVOList = new ArrayList<>();

        for (Setmeal setmeal : setmealList) {
            // 复制属性
            SetmealVO setmealVO = new SetmealVO();
            BeanUtils.copyProperties(setmeal, setmealVO);

            // 取出 id
            Long setmealCategoryId = setmeal.getCategoryId();

            // 查询分类名称
            String categoryName = categoryService.getById(setmealCategoryId).getName();

            // 赋值分类名称
            setmealVO.setCategoryName(categoryName);

            // 插入返回数据列表
            setmealVOList.add(setmealVO);
        }


        // 构造分页结果
        PageResult pageResult = new PageResult();

        // 设置属性
        // TODO 分页查询失败，需要修改
        pageResult.setTotal(page.getRecords().size());

        // 手动分页

        // 左端 = （页数 - 1）* 每页条数
        int l = (pageNum - 1) * pageSize;

        // 左端起点超出起点
        if (l >= page.getRecords().size()) {
            return pageResult;
        }

        // 右端 = 左端 +
        int r = l + pageSize;
        r = min(r, page.getRecords().size());

        pageResult.setRecords(setmealVOList.subList(l, r));
        return pageResult;
    }

    @Override
    @Transactional
    public void deleteByIds(List<Long> ids) {

        for (Long id : ids) {
            Setmeal setmeal = setmealMapper.selectById(id);

            // 判断套餐是否在售
            if (Objects.equals(setmeal.getStatus(), StatusConstant.ENABLE)) {
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }

            setmealMapper.deleteById(id);
            setmealDishService.deleteBySetmealId(id);


        }


    }

    @Override
    @Transactional
    public SetmealVO queryByIdWithDish(Long id) {
        // 查询数据
        Setmeal setmeal = setmealMapper.selectById(id);
        List<SetmealDish> setmealDishList = setmealDishService.getBySetmealId(id);

        SetmealVO setmealVO = new SetmealVO();
        BeanUtils.copyProperties(setmeal, setmealVO);

        setmealVO.setSetmealDishes(setmealDishList);

        return setmealVO;
    }

    @Override
    public Setmeal updateById(SetmealDTO setmealDTO) {

        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        setmeal.setUpdateTime(LocalDateTime.now());
        setmeal.setUpdateUser(BaseContext.getCurrentId());

        // 更新套餐表数据
        setmealMapper.updateById(setmeal);

        // 获取套餐 id
        Long setmealId = setmealDTO.getId();
        setmealDishService.deleteBySetmealId(setmealId);

        List<SetmealDish> setmealDishList = setmealDTO.getSetmealDishes();
        setmealDishList.forEach(setmealDish -> {
            setmealDish.setSetmealId(setmealId);
        });

        setmealDishService.createBatch(setmealDishList);

        return null;
    }

    @Override
    @Transactional
    public Setmeal startOrStop(Long id, Integer status) {

        // 获取套餐数据
        Setmeal setmeal = setmealMapper.selectById(id);

        // 停售套餐
        if (Objects.equals(status, StatusConstant.DISABLE)) {
            // 修改状态
            setmeal.setStatus(StatusConstant.DISABLE);
            // 更新数据
            setmealMapper.updateById(setmeal);
            return setmeal;
        }

        // 起售套餐，需要进行检查

        // 首先获取套餐包含的菜品
        List<SetmealDish> setmealDishList = setmealDishService.getBySetmealId(id);
        // 遍历菜品列表，查看有无停售菜品
        for (SetmealDish setmealDish : setmealDishList) {
            // 获取菜品 id
            Long dishId = setmealDish.getDishId();
            Dish dish = dishService.queryById(dishId);
            if (Objects.equals(dish.getStatus(), StatusConstant.DISABLE)) {
                throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
            }

        }
        setmeal.setStatus(StatusConstant.ENABLE);
        setmealMapper.updateById(setmeal);

        return setmeal;
    }


}

